﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;

namespace SuuntoAmbitConnector
{
    public class SuuntoAmbitFileReader
    {
        private DirectoryInfo workoutFileRepository;
        private string currentWorkoutFileName;
        private XmlDocument _currentWorkoutXmlFile;

        public SuuntoAmbitFileReader(string suuntoAmbitWorkoutRepository)
        {
            workoutFileRepository = new DirectoryInfo(suuntoAmbitWorkoutRepository);
        }
        
        public bool HasWorkoutFiles 
        {
            get
            {
                return workoutFileRepository.GetFiles().Count() > 0;
            }
        }

        public XmlDocument ReadWorkoutFileAsXml(string workoutFileName)
        {
            var xmlDeclaration = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
            var xmlDocument = new XmlDocument();

            var workoutFiles = workoutFileRepository.GetFiles(workoutFileName, SearchOption.TopDirectoryOnly);

            if (workoutFiles.Count() == 0)
                throw new FileNotFoundException("Suunto workout not found", workoutFileName);

            using (var workoutFileStream = new System.IO.StreamReader(workoutFiles.First().FullName))
            {
                var fileContent = workoutFileStream.ReadToEnd().Replace(xmlDeclaration, "");
                                
                // Suunto files are not valid since they have multiple root elements. Adding artifical root to prevent exceptions.
                xmlDocument.LoadXml(string.Format("{0}<root>{1}</root>", xmlDeclaration, fileContent));
            }
            
            return xmlDocument;

        }

        public void LoadWorkoutFile(string workoutFileName)
        {
            this.CurrentWorkoutXmlFile = ReadWorkoutFileAsXml(workoutFileName);
            this.currentWorkoutFileName = workoutFileName;
        }

        public string ReadSingleValue(string nodeName)
        {
            if (string.IsNullOrEmpty(nodeName))
                throw new ArgumentNullException("nodeName");
                        
            return this.CurrentWorkoutXmlFile.SelectSingleNode(GetXPathSelector(nodeName)).InnerText;
        }

        public DateTime ReadSingleValueAsDateTime(string nodeName)
        {
            var value = ReadSingleValue(nodeName);
            return DateTime.Parse(value);
        }

        public int ReadSingleValueAsInt(string nodeName)
        {
            var value = ReadSingleValue(nodeName);
            return int.Parse(value);
        }

        public double ReadSingleValueAsDouble(string nodeName)
        {
            var value = ReadSingleValue(nodeName);
            return double.Parse(value);
        }

        public long ReadSingleValueAsLong(string nodeName)
        {
            var value = ReadSingleValue(nodeName);
            return long.Parse(value);
        }

        private string GetXPathSelector(string nodeName)
        {
            return string.Format("root/header/{0}", nodeName);
        }

        public bool IsWorkoutFileLoaded 
        {
            get
            {
                return !string.IsNullOrEmpty(GetWorkoutFileName());
            }
        }

        public string GetWorkoutFileName()
        {
            return this.currentWorkoutFileName;
        }

        private XmlDocument CurrentWorkoutXmlFile
        {
            get
            {
                if (!this.IsWorkoutFileLoaded)
                    throw new InvalidOperationException("A Suunto Ambit workout file must be loaded using method LoadWorkoutFile()");
                
                return this._currentWorkoutXmlFile;
            }

            set
            {
                this._currentWorkoutXmlFile = value;
            }
        }

        

        public double ReadDuration()
        {
            return ReadSingleValueAsDouble("Duration");
        }

        public long ReadDistance()
        {
            long distance = 0;
            try
            {
                distance = ReadSingleValueAsLong("Distance");
            }
            catch (Exception)
            {                
            }
            
            return distance;
        }

        public DateTime ReadStartDate()
        {
            return ReadSingleValueAsDateTime("DateTime");
        }

        public int ReadActivityType()
        {
            return ReadSingleValueAsInt("ActivityType");
        }

        public Workout CreateWorkoutObject()
        {
            var workoutStartDate = this.ReadStartDate();
            var workoutActivity = this.ReadActivityType();
            var workoutDuration = Convert.ToInt64(this.ReadDuration());
            var workoutDistance = this.ReadDistance();
            
            var workout = new Workout(workoutStartDate, workoutActivity, workoutDuration, "Created by Suunto2Endomondo");
            workout.DistanceInMeters = workoutDistance;

            return workout;
        }
    }
}
